/*
 * Created on 2005-2-26
 *
 */
package com.hd123.rumba.user;

import java.sql.Blob;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import net.sf.hibernate.HibernateException;

import org.apache.log4j.Logger;

import com.hd123.rumba.cartridge.FVRumbaSystem;
import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.exception.ParameterException;
import com.hd123.rumba.exception.StringTooLongException;
import com.hd123.rumba.runtime.BaseEntity;
import com.hd123.rumba.runtime.NamingMgr;
import com.hd123.rumba.util.AccessMode;
import com.hd123.rumba.util.SecurityUtil;

/**
 * @author caili
 * 
 */
public class User extends BaseEntity implements IUser {
  /** @deprecated */
  public static String CAPTION_USER = CUser.CAPTION_USER;

  /** 构件包前缀 */
  public static String FUNCV_PREFIX = FVRumbaSystem.FUNCV_PREFIX;

  private String login;
  /** @deprecated */
  public static String CAPTION_LOGIN = CUser.CAPTION_LOGIN;
  /** @deprecated */
  public static final int LENGTH_login = CUser.LENGTH_LOGIN;

  private String password;
  /** @deprecated */
  public static String CAPTION_PASSWORD = CUser.CAPTION_PASSWORD;
  /** @deprecated */
  public static final int LENGTH_password = CUser.LENGTH_PASSWORD;

  private Boolean online;
  /** @deprecated */
  public static String CAPTION_ONLINE = CUser.CAPTION_ONLINE;

  private Date validFrom;
  /** @deprecated */
  public static String CAPTION_VALIDFROM = CUser.CAPTION_VALIDFROM;

  private Date validTo;
  /** @deprecated */
  public static String CAPTION_VALIDTO = CUser.CAPTION_VALIDTO;

  private String remark;
  /** @deprecated */
  public static String CAPTION_REMARK = CUser.CAPTION_REMARK;
  /** @deprecated */
  public static final int LENGTH_remark = CUser.LENGTH_REMARK;

  private String Name;
  /** @deprecated */
  public static String CAPTION_NAME = CUser.CAPTION_NAME;
  /** @deprecated */
  public static final int LENGTH_name = CUser.LENGTH_NAME;

  private IProfile profile;
  /** @deprecated */
  public static final String CAPTION_PROFILE = CUser.CAPTION_PROFILE;

  private IDepartment department;
  /** @deprecated */
  public static final String CAPTION_DEPARTMENT = CUser.CAPTION_DEPARTMENT;

  private Blob image;
  /** @deprecated */
  public static final String CAPTION_IMAGE = CUser.CAPTION_IMAGE;

  /** 是否启用令牌登录 */
  private Boolean useToken = Boolean.FALSE;
  /** 令牌序列号 */
  private String tokenSn;
  /** 令牌PIN码 */
  private String tokenPin;

  // private Set userPermissions = new HashSet();
  // private Set userRoles = new HashSet();
  private Map assignedPermissionsMap = null;
  private Map commissionedPermissionsMap = null;

  public static final String PERMISSION_EDIT = "用户.编辑权"; /* "user.edit"; */
  public static final String PERMISSION_VIEW = "用户.查看权";/* "user.view"; */

  /** @deprecated */
  public static final String VALUE_SYSTEM_OPERATOR = "Tango[Tango]";

  public String getFullLogin() throws BusinessException {
    return getLogin() + "@" + getDomain().getCode();
  }

  /**
   * @param image
   *            The image to set.
   */
  public void setImage(Blob image) {
    this.image = image;
  }

  /**
   * @return Returns the image.
   */
  public Blob getImage() {
    return image;
  }

  /**
   * @return Returns the department.
   */
  public IDepartment getDepartment() {
    return department;
  }

  /**
   * @param department
   *            The department to set.
   */
  public void setDepartment(IDepartment department) {
    this.department = department;
  }

  /**
   * @return Returns the name.
   */
  public String getName() {
    return Name;
  }

  /**
   * @param name
   *            The name to set.
   */
  public void setName(String name) throws StringTooLongException {
    if (name != null) {
      name = truncate(name, CUser.LENGTH_NAME, "name", CUser.CAPTION_NAME);
    }
    Name = name;
  }

  /**
   * @return Returns the profile.
   */
  public IProfile getProfile() {
    return profile;
  }

  /**
   * @param profile
   *            The profile to set.
   */
  public void setProfile(IProfile profile) {
    this.profile = profile;
  }

  public String getRemark() {
    return remark;
  }

  public void setRemark(String remark) throws StringTooLongException {
    if (remark != null) {
      remark = truncate(remark, CUser.LENGTH_REMARK, "remark", CUser.CAPTION_REMARK);
    }
    this.remark = remark;
  }

  // private Set getUserRoles() {
  // return userRoles;
  // }
  //
  // private void setUserRoles(Set userRoles) {
  // this.userRoles = userRoles;
  // }
  //
  // private Set getUserPermissions() {
  // return userPermissions;
  // }
  //
  // private void setUserPermissions(Set userPermissions) {
  // this.userPermissions = userPermissions;
  // }

  public String getLogin() {
    return login;
  }

  public void setLogin(String login) throws StringTooLongException {
    if (login != null) {
      login = login.trim().toUpperCase();
      login = truncate(login, CUser.LENGTH_LOGIN, "login", CUser.CAPTION_LOGIN);
    }
    this.login = login;
  }

  public Boolean getOnline() {
    return online;
  }

  public void setOnline(Boolean online) {
    this.online = online;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) throws StringTooLongException {
    if (password != null) {
      password = truncate(password, CUser.LENGTH_PASSWORD, "password", CUser.CAPTION_PASSWORD);
    }
    this.password = password;
  }

  public Date getValidFrom() {
    return validFrom;
  }

  public void setValidFrom(Date validFrom) {
    this.validFrom = validFrom;
  }

  public Date getValidTo() {
    return validTo;
  }

  public void setValidTo(Date validTo) {
    this.validTo = validTo;
  }

  public String getTokenPin() {
    return tokenPin;
  }

  public void setTokenPin(String tokenPin) throws StringTooLongException {
    if (tokenPin != null)
      tokenPin = truncate(tokenPin, CUser.LENGTH_TOKENPIN, "tokenPin", CUser.CAPTION_TOKENPIN);
    this.tokenPin = tokenPin;
  }

  public String getTokenSn() {
    return tokenSn;
  }

  public void setTokenSn(String tokenSn) throws StringTooLongException {
    if (tokenSn != null)
      tokenSn = truncate(tokenSn, CUser.LENGTH_TOKENSN, "tokenSn", CUser.CAPTION_TOKENSN);
    this.tokenSn = tokenSn;
  }

  public Boolean getUseToken() {
    return useToken;
  }

  public void setUseToken(Boolean useToken) {
    this.useToken = useToken;
  }

  public Vector getPermissionIds() throws BusinessException {
    buildPermissionMap();
    Vector v = new Vector();
    v.addAll(assignedPermissionsMap.values());
    v.addAll(commissionedPermissionsMap.values());
    return v;
  }

  public boolean hasPermission(String permissionId) throws BusinessException {
    buildPermissionMap();
    return assignedPermissionsMap.containsKey(permissionId)
        || commissionedPermissionsMap.containsKey(permissionId);
  }

  public boolean hasPermissions(PE pe) throws BusinessException {
    buildPermissionMap();
    return pe.caculate(this);
  }

  public boolean hasPerm(String permId) throws BusinessException {
    if (permId == null)
      return true;
    else
      return hasPermission(permId);
  }

  public boolean hasPerm(PE pe) throws BusinessException {
    if (pe == null)
      return true;
    else
      return hasPermissions(pe);
  }

  public boolean hasAssignedPermission(String permissionId) throws BusinessException {
    buildPermissionMap();
    return assignedPermissionsMap.containsKey(permissionId);
  }

  public int getFieldAccessMode(String fieldPermId) throws BusinessException {
    int result = AccessMode.INVISIBLE;
    if (hasPermission(fieldPermId + CPermission.SUFFIX_PERMISSION_VIEW))
      result = AccessMode.READONLY;
    if (hasPermission(fieldPermId + CPermission.SUFFIX_PERMISSION_EDIT))
      result = AccessMode.READWRITE;
    return result;
  }

  private void buildPermissionMap() throws BusinessException {
    if (assignedPermissionsMap != null && commissionedPermissionsMap != null)
      return;
    try {
      IUserMgr userMgr = (IUserMgr) NamingMgr.getInstance().lookupMgr(IUserMgr.class);
      assignedPermissionsMap = Collections.synchronizedMap(new HashMap());
      List list = userMgr.createPermissionsList(this);
      for (int i = 0; i < list.size(); ++i) {
        IPermission perm = (IPermission) list.get(i);
        assignedPermissionsMap.put(perm.getCode(), perm.getCode());
      }
      IRoleMgr roleMgr = (IRoleMgr) NamingMgr.getInstance().lookupMgr(IRoleMgr.class);
      list = userMgr.createRolesList(this);
      for (int i = 0; i < list.size(); ++i) {
        IRole role = (IRole) list.get(i);
        List list2 = roleMgr.createPermissionsList(role);
        for (int j = 0; j < list2.size(); ++j) {
          IPermission perm = (IPermission) list2.get(j);
          assignedPermissionsMap.put(perm.getCode(), perm.getCode());
        }
      }

      list = userMgr.createCommissionedPermissionsList(this);
      commissionedPermissionsMap = Collections.synchronizedMap(new HashMap());
      Date today = new Date();
      for (int i = 0; i < list.size(); ++i) {
        IPermissionCommission perm = (IPermissionCommission) list.get(i);
        if (today.after(perm.getValidFrom()) && today.before(perm.getValidTo()))
          commissionedPermissionsMap.put(perm.getPermission().getCode(), perm.getPermission()
              .getCode());
      }
    } catch (HibernateException e) {
      Logger.getLogger(this.getClass()).warn(e.getMessage());
    } catch (ParameterException e) {
      Logger.getLogger(this.getClass()).warn(e.getMessage());
    }
  }

  public String getCodeName() {
    return getLogin() + "[" + getName() + "]";
  }

  public String getNameCode() {
    return getName() + "[" + getLogin() + "]";
  }

  /**
   * @param codeName
   * @return String[0]=Login, String[1]=name
   */
  public static String[] parseCodeName(String codeName) {
    String[] result = new String[] {
        "", "" };
    if (codeName != null) {
      int i = codeName.indexOf("[");
      if (i > 0) {
        result[0] = codeName.substring(0, i);
        result[1] = codeName.substring(i + 1);
      }
    }
    return result;
  }

  public void encodePassword(String fpassword) {
    String pas = SecurityUtil.encodeString(fpassword);
    if (pas != null)
      password = pas;
  }

  public void addToPermissionMap(IPermission perm) throws BusinessException {
    if (assignedPermissionsMap == null)
      assignedPermissionsMap = Collections.synchronizedMap(new HashMap());
    assignedPermissionsMap.put(perm.getCode(), perm.getCode());
  }

  public void addToPermissionMap(List<String> permCodes) throws BusinessException {
    if (assignedPermissionsMap == null)
      assignedPermissionsMap = Collections.synchronizedMap(new HashMap());
    if (commissionedPermissionsMap == null)
      commissionedPermissionsMap = Collections.synchronizedMap(new HashMap());
    if (permCodes != null)
      for (String permCode : permCodes)
        assignedPermissionsMap.put(permCode, permCode);
  }

  public void removeFromPermissionMap(IPermission perm) throws BusinessException {
    assignedPermissionsMap.remove(perm.getCode());
  }
}
